﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security.Cryptography;
using System.Text.RegularExpressions;

namespace CRCMD5Solver
{
	using cset = Properties.Settings;

	public partial class MainForm : Form
	{
		public MainForm()
		{
			InitializeComponent();
		}

		private List<string> videoList;
		private List<string> otherList;

		//private readonly string[] va = { ".mp4", ".mkv", ".avi" };
		//private readonly string[] other = { ".zip", ".7z", ".rar" };

		private void buttonStart_Click(object sender, EventArgs e)
		{
			this.buttonStart.Enabled = false;
			this.buttonStart.Text = "Running.";

			this.backgroundWorkerMain.RunWorkerAsync();
		}

		private void textBoxDirectory_DragDrop(object sender, DragEventArgs e)
		{
			var obj = ((string[])e.Data.GetData(DataFormats.FileDrop))[0];
			textBoxDirectory.Text = Path.GetDirectoryName(obj);
			this.GetFiles();
		}

		private void GetFiles()
		{
			this.videoList = new List<string>();
			this.otherList = new List<string>();
			dataGridViewFileList.Rows.Clear();
			var filelist = Directory.GetFiles(textBoxDirectory.Text);

			foreach (var fi in filelist)
			{
				var extn = Path.GetExtension(fi);
				if (cset.Default.video.Contains(extn))
					this.videoList.Add(fi);
				else if (cset.Default.other.Contains(extn))
					this.otherList.Add(fi);
			}

			dataGridViewFileList.Rows.Add(this.otherList.Count);
			for (int i = 0; i < this.otherList.Count; i++)
			{
				dataGridViewFileList[2, i].Value = Path.GetFileName(this.otherList[i]);
				dataGridViewFileList[1, i].Value = false;
			}
			dataGridViewFileList.Rows.Add(this.videoList.Count);
			for (int i = 0; i < this.videoList.Count; i++)
			{
				dataGridViewFileList[2, i + this.otherList.Count].Value = Path.GetFileName(this.videoList[i]);
				dataGridViewFileList[1, i + this.otherList.Count].Value = true;
			}
		}

		private void textBoxDirectory_DragEnter(object sender, DragEventArgs e)
		{
			if (e.Data.GetDataPresent(DataFormats.FileDrop))
				e.Effect = DragDropEffects.Link;
			else
				e.Effect = DragDropEffects.None;
		}

		private void backgroundWorkerMain_DoWork(object sender, DoWorkEventArgs e)
		{
			if (!Directory.Exists(textBoxDirectory.Text))
			{
				MessageBox.Show("Can not find the Directory.");
				return;
			}
			var filelist = Directory.GetFiles(textBoxDirectory.Text);

			if (this.checkBoxCRCCheck.Checked)
				this.CRCCheck();
			//this.MD5Gen();
		}

		private void backgroundWorkerMain_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			this.buttonStart.Enabled = true;
			this.buttonStart.Text = "Start";
		}

		private void backgroundWorkerMain_ProgressChanged(object sender, ProgressChangedEventArgs e)
		{
			this.buttonStart.Text = e.ProgressPercentage.ToString();
		}

		private void MD5Gen()
		{
			var sb = new StringBuilder();
			var md5Class = new MD5CryptoServiceProvider();

			foreach (var fi in this.videoList)
				using (var fs = new FileStream(fi, FileMode.Open, FileAccess.Read))
				{
					var md5 = new StringBuilder();
					foreach (var i in md5Class.ComputeHash(fs))
						md5.Append(i.ToString("X2"));
					sb.AppendFormat("{1} {0}\n", Path.GetFileName(fi), md5.ToString());
				}

			foreach (var fi in this.otherList)
				using (var fs = new FileStream(fi, FileMode.Open, FileAccess.Read))
				{
					var md5 = new StringBuilder();
					foreach (var i in md5Class.ComputeHash(fs))
						md5.Append(i.ToString("X2"));
					sb.AppendFormat("{1} {0}\n", Path.GetFileName(fi), md5.ToString());
				}

			File.WriteAllText(Path.Combine(textBoxDirectory.Text, "Check.md5"), sb.ToString(), Encoding.UTF8);
			this.backgroundWorkerMain.ReportProgress(50);
			MessageBox.Show("Finish.");
		}

		private void CRCCheck()
		{
			var sb = new StringBuilder();
			var crcCalcor = new crc32n();
			foreach (var fi in this.videoList)
			{
				var crc32 = string.Empty;
				var crcGold = string.Empty;

				using (var fs = File.OpenRead(fi))
					crc32 = crcCalcor.CRC(fs).ToString("X8");

				var r = string.Format(@"[\[\(][_\s]*([0-9a-fA-F]*)[_\s]*[\]\)]\{0}", Path.GetExtension(fi));
				var crcInName = Regex.Match(Path.GetFileName(fi), r);
				if (crcInName.Success)
				{
					crcGold = crcInName.Groups[1].Value.ToUpper();
				}
				else
				{
				}

				if (string.Compare(crc32, crcGold) == 0)
					sb.AppendFormat("{1}   {0}\n", Path.GetFileName(fi), "Pass  ");
				else
					sb.AppendFormat("{1}   {0}\n\tIn filename:{2}\tCalc:{3}\n", Path.GetFileName(fi), "--Fail", crcGold, crc32);
			}
			File.WriteAllText(Path.Combine(textBoxDirectory.Text, "CheckCRC.log"), sb.ToString(), Encoding.UTF8);
		}
	}
}
